 /*******************************************************************************
  * Copyright (c) 2004, 2005 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
  * Contributors:
  * IBM Corporation - initial API and implementation
  *******************************************************************************/
 package org.eclipse.ui.internal.components;

 import org.eclipse.core.runtime.CoreException;
 import org.eclipse.core.runtime.IConfigurationElement;
 import org.eclipse.core.runtime.IStatus;
 import org.eclipse.core.runtime.Platform;
 import org.eclipse.core.runtime.Status;
 import org.eclipse.osgi.util.NLS;
 import org.eclipse.ui.PlatformUI;
 import org.eclipse.ui.internal.components.framework.ClassIdentifier;
 import org.eclipse.ui.internal.components.framework.ComponentException;
 import org.eclipse.ui.internal.components.framework.ServiceFactory;
 import org.eclipse.ui.internal.components.registry.ComponentRegistry;
 import org.eclipse.ui.internal.components.registry.ComponentScope;
 import org.eclipse.ui.internal.components.registry.ExtensionPointManager;
 import org.eclipse.ui.internal.components.registry.IComponentScope;
 import org.eclipse.ui.internal.components.registry.ServiceExtensionPoint;
 import org.eclipse.ui.internal.misc.StatusUtil;
 import org.osgi.framework.Bundle;


 /**
  * Creates an IComponent, given a set of local services.
  *
  * @since 3.1
  */
 public class ComponentUtil {
     
     public static final Object [] EMPTY_ARRAY = new Object [0];
     
     private static ComponentRegistry registry;
     private static ExtensionPointManager uiExtensionPoints = null;
     private static ServiceExtensionPoint partServices = null;

     
     private ComponentUtil() {
     }
     
     public static ComponentRegistry getRegistry() {
         if (registry != null) {
             return registry;
         }
         registry = new ComponentRegistry();
         Bundle uiBundle = Platform.getBundle(PlatformUI.PLUGIN_ID);
         uiExtensionPoints = new ExtensionPointManager(uiBundle);
         partServices = new ServiceExtensionPoint(uiExtensionPoints, ComponentUtil.registry);

         return registry;
     }
     
     public static void disposeRegistry() {
       if (partServices != null) {
           partServices.dispose();
           partServices = null;
       }
       
       if (uiExtensionPoints != null) {
           uiExtensionPoints.dispose();
           uiExtensionPoints = null;
       }
       
       registry = null;
     }
     
     public static String getSimpleClassName(String fullyQualifiedClassName) {
         int idx = fullyQualifiedClassName.lastIndexOf('.') + 1;
         
         return fullyQualifiedClassName.substring(idx, fullyQualifiedClassName.length());
     }
     
     public static Throwable getCause(Throwable toQuery) {
         return StatusUtil.getCause(toQuery);
     }
     
     public static Class loadClass(ClassIdentifier type) throws ComponentException {
         try {
             Bundle pluginBundle = Platform.getBundle(type.getNamespace());
             Class result = pluginBundle.loadClass(type.getTypeName());
             return result;
         } catch (ClassNotFoundException e) {
             throw new ComponentException(type.getTypeName(),
                    NLS.bind(ComponentMessages.ComponentUtil_class_not_found,
                             type.getNamespace(), type.getTypeName()), null);
         }
     }
     
     public static final ClassIdentifier getClassFromInitializationData(IConfigurationElement config, Object data) throws CoreException {
         
         if (!(data instanceof String )) {
             String msg = NLS.bind(
                     ComponentMessages.ReflectionFactory_missing_data, config.toString());
             
             throw new CoreException(new Status(IStatus.ERROR, config.getNamespace(), Status.OK,
                     msg, null));
         }
         
         return new ClassIdentifier(config.getNamespace(), (String )data);
     }
     
     public static String getMessage(Throwable toQuery) {
         String msg = toQuery.getMessage();
         
         if (msg == null) {
             msg = toQuery.toString();
         }
         
         return msg;
     }
     
 // /**
 // * Creates and initializes a component implementation, given a Class that implements
 // * IComponent. Returns a fully-initialized component.
 // *
 // * @param desiredService
 // * @param otherServices
 // * @return a fully initialized component
 // * @throws ComponentException if unable to create or initialize the component
 // */
 // public static Object createComponentImplementation(Class desiredService, IComponentProvider otherServices) throws ComponentException {
 // try {
 // Assert.isTrue(IComponent.class.isAssignableFrom(desiredService));
 //
 // IComponent component = (IComponent)desiredService.newInstance();
 //
 // component.init(otherServices);
 //
 // return component;
 // } catch (ComponentException e) {
 // throw new ComponentException(desiredService, e);
 // } catch (IllegalArgumentException e) {
 // throw new ComponentException(desiredService, e);
 // } catch (InstantiationException e) {
 // throw new ComponentException(desiredService, e);
 // } catch (IllegalAccessException e) {
 // throw new ComponentException(desiredService, e);
 // }
 // }

     public static String getAttribute(IConfigurationElement element, String attributeId) throws CoreException {
         String result = element.getAttribute(attributeId);
         if (result == null) {
             throw new CoreException(new Status(IStatus.ERROR, element.getNamespace(),
                     IStatus.OK, NLS.bind(ComponentMessages.ComponentUtil_missing_attribute,
                             new Object [] {element.getName(), attributeId,
                             element.getDeclaringExtension().getExtensionPointUniqueIdentifier()}), null
                             ));
         }
         
         return result;
     }
     
     public static Throwable getMostSpecificCause(Throwable exception) {
         return getMostSpecificException(getCause(exception));
     }
     
     /**
      * @since 3.1
      *
      * @param exception
      * @return
      */
     private static Throwable getMostSpecificException(Throwable exception) {
         Throwable cause = getCause(exception);
         if (cause == null || cause == exception) {
             return exception;
         }
         
         return getMostSpecificException(cause);
     }

     /**
      * @param implementation
      * @throws ComponentException
      */
     public static Object createInstance(Class implementation) throws ComponentException {
         try {
             return implementation.newInstance();
         } catch (InstantiationException e) {
             throw new ComponentException(implementation, e);
         } catch (IllegalAccessException e) {
             throw new ComponentException(implementation, e);
         }
     }

     /**
      * Returns meta-information about the component scope with the given ID.
      * This is intended for introspection without activating plugins.
      * For example, this could be used to print out a list of all services
      * available in a particular scope. Clients who want to instantiate services
      * in the given scope should call <code>getContext</code> instead.
      *
      * <i>EXPERIMENTAL</i> it is likely that this method will change in the
      * near future.
      *
      * @param scope scope ID
      * @return an IComponentScope containing meta-information about the given
      * scope ID, or null if the given scope is unknown
      */
     public static IComponentScope getScope(String scope) {
         return getRegistry().getScope(scope);
     }

     /**
      * Returns a context for the given scope ID. This context can be used
      * to instantiate components from the org.eclipse.core.components.services
      * that are included in the given scope.
      *
      * <p>
      * The resulting context will be able to create components if:
      * <ul>
      * <li>The component is belongs to the same scope</li>
      * <li>The component is belongs to a scope which is included in the given scope</li>
      * </ul>
      *
      * <p>
      * Note that components that are required by the given scope will show up
      * as dependencies in the resulting context but cannot be created by
      * the context.
      * </p>
      *
      * <p>
      * All dependencies of the given context should be satisfied before
      * attempting to instantiate any objects from the context.
      * </p>
      *
      * @param scope ID of the scope to return
      * @return a container context for the given scope
      */
     public static ServiceFactory getContext(String scope) {
         IComponentScope s = getScope(scope);
         
         if (s == null) {
             return null;
         }
         
         return ((ComponentScope)s).getContext();
     }
     

     
 }

